#include "comm/cpu_instr.h"
#include "cpu/cpu.h"
#include "irq/irq.h"
#include "os_cfg.h"
#include "tools/log.h"

static gate_desc_t irq_table[LDT_TABLE_SIZE];

 void exception_handle_default(void);
 void exception_handle_divide(void);
void dump_core_regs(exception_frame_t * frame);
 void do_handler_default( exception_frame_t *frame){
    log_printf("default..irq,[error_code]:%d,num:%d \n",frame->error_code,frame->num);
    while (1)
    {
      hlt();
    }
 }

 void do_handler_divide( exception_frame_t *frame){
   log_printf("divide..irq");
   dump_core_regs(frame);
    while (1)
    {
      hlt();
    }
 }
static void init_pic(void) {
    // 边缘触发，级联，需要配置icw4, 8086模式
    outb(PIC0_ICW1, PIC_ICW1_ALWAYS_1 | PIC_ICW1_ICW4);

    // 对应的中断号起始序号0x20
    outb(PIC0_ICW2, IRQ_PIC_START);

    // 主片IRQ2有从片
    outb(PIC0_ICW3, 1 << 2);

    // 普通全嵌套、非缓冲、非自动结束、8086模式
    outb(PIC0_ICW4, PIC_ICW4_8086);

    // 边缘触发，级联，需要配置icw4, 8086模式
    outb(PIC1_ICW1, PIC_ICW1_ICW4 | PIC_ICW1_ALWAYS_1);

    // 起始中断序号，要加上8
    outb(PIC1_ICW2, IRQ_PIC_START + 8);

    // 没有从片，连接到主片的IRQ2上
    outb(PIC1_ICW3, 2);

    // 普通全嵌套、非缓冲、非自动结束、8086模式
    outb(PIC1_ICW4, PIC_ICW4_8086);

    // 禁止所有中断, 允许从PIC1传来的中断
    outb(PIC0_IMR, 0xFF & ~(1 << 2));
    outb(PIC1_IMR, 0xFF);
}
void irq_init (void){
    for(uint32_t i=0;i<LDT_TABLE_SIZE;i++){
        gate_desc_set(irq_table+i,KERNEL_SELECTOR_CS,(uint32_t)exception_handle_default,GATE_P_PRESENT | GATE_DPL0 | GATE_TYPE_IDT  );
    }
    gate_desc_set(irq_table+0,KERNEL_SELECTOR_CS,(uint32_t)exception_handle_divide,GATE_P_PRESENT | GATE_DPL0 | GATE_TYPE_IDT  );

    lidt((uint32_t)irq_table, sizeof(irq_table));
    	// 初始化pic 控制器
	init_pic();
}

void gate_desc_set(gate_desc_t *desc,uint16_t selector, uint32_t base, uint16_t attr){
    desc->offset15_0 = base &0xFFFF;
    desc->selector = selector;
    desc->attr = attr;
    desc->offset31_16 = (base>>16)&0xFFFF;
}

 void dump_core_regs(exception_frame_t * frame) {
    // 打印CPU寄存器相关内容
    log_printf("IRQ: %d, error code: %d.", frame->num, frame->error_code);
    log_printf("CS: %d\r\nDS: %d\r\nES: %d\r\nSS: %d\r\nFS:%d\r\nGS:%d",
               frame->cs, frame->ds, frame->es, frame->ds, frame->fs, frame->gs
    );
    log_printf("EAX:0x%x\r\n"
                "EBX:0x%x\r\n"
                "ECX:0x%x\r\n"
                "EDX:0x%x\r\n"
                "EDI:0x%x\r\n"
                "ESI:0x%x\r\n"
                "EBP:0x%x\r\n"
                "ESP:0x%x\r\n",
               frame->eax, frame->ebx, frame->ecx, frame->edx,
               frame->edi, frame->esi, frame->ebp, frame->esp);
    log_printf("EIP:0x%x\r\nEFLAGS:0x%x\r\n", frame->eip, frame->eflags);
}